package com.arch.flink.state;

import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.restartstrategy.RestartStrategies;
import org.apache.flink.api.common.restartstrategy.RestartStrategies.RestartStrategyConfiguration;
import org.apache.flink.api.common.time.Time;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.util.concurrent.TimeUnit;

/**
 *
 * 功能描述: 不配置重启策略,默认异常后就失败:
 * 操作步骤:
 *      1. 直接运行程序，作业5分钟内5次失败，测终止作业，每次启动间隔5秒钟，当在5分钟内第5次异常后，终止作业。
 *
 *      2. 修改策略failureRateRestart(5, Time.of(5, TimeUnit.MINUTES), Time.of(5, TimeUnit.SECONDS)))，
 *          也即是 10s 内重启 5 次,就不会停止作业,一直会重启。
 *
 * @author pizhihui
 * @date 2024-05-28 22:42
 */
public class D3_FailureRateRestart {


    private final static Logger log = LoggerFactory.getLogger(D3_FailureRateRestart.class);

    public static void main(String[] args) throws Exception {


        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        //
        RestartStrategyConfiguration strategy = RestartStrategies.
                failureRateRestart(5, Time.of(5, TimeUnit.MINUTES), Time.of(2, TimeUnit.SECONDS));
        env.setRestartStrategy(strategy);

        DataStreamSource<Tuple3<String, Integer, Long>> source = env.addSource(new SourceFunction<Tuple3<String, Integer, Long>>() {

            @Override
            public void run(SourceContext<Tuple3<String, Integer, Long>> ctx) throws Exception {
                int index = 1;
                while (true) {
                    // 1s 产生一条数据
                    ctx.collect(Tuple3.of("key", index++, System.currentTimeMillis()));
                    Thread.sleep(1000);
                }
            }

            @Override
            public void cancel() {

            }
        });

        source.map(new MapFunction<Tuple3<String, Integer, Long>, Tuple3<String, Integer, String>>() {
            @Override
            public Tuple3<String, Integer, String> map(Tuple3<String, Integer, Long> event) throws Exception {
                if (event.f1 % 10 == 0) {
                    String msg = String.format("Bad data [%d] ...", event.f1);
                    log.error(msg);
                    throw new RuntimeException(msg);
                }
                return Tuple3.of(event.f0, event.f1, new Timestamp(System.currentTimeMillis()).toString());

            }
        }).print();


        env.execute("no restart job");

    }

}
